using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;

using NUnit.Framework;

using Forum.Contracts;
using NSimpleDB.Service.Contract;

namespace Forum.Tests.DataAccess
{
    [TestFixture]
    public class testDataAccess
    {
        #region setup/teardown
        private const string ForumsDomainName = "Forums";

        private IDataAccess db;
        private ISimpleDBService sdb;

        [SetUp]
        public void InitDB()
        {
            System.IO.File.Delete("test.vdb3");
            this.db = new Forum.DataAccess.DataAccessAdapter("test.vdb3");
            this.sdb = new NSimpleDB.Service.VistaDb.VistaDbSimpleDBService("test.vdb3");
        }

        [TearDown]
        public void FiniDB()
        {
            this.db.Clear();
            this.db.Dispose();
            this.sdb.Close();
        }
        #endregion


        [Test]
        public void testInitializeAndClear()
        {
            this.db.Clear();
            Assert.AreEqual(0, this.sdb.ListDomains().Length);

            this.db.Initialize();
            Assert.AreEqual(1, this.sdb.ListDomains().Length);
        }


        [Test]
        public void testStoreRootPostings()
        {
            this.db.Initialize();

            Assert.AreEqual(0, this.sdb.Query(testDataAccess.ForumsDomainName, "['isRoot'='true']").Length);

            Posting p;
            p = new Posting();
            p.Subject = "s1";
            p.Text = "t1";
            p.CreatedBy = "c1";
            this.db.StorePosting(p);

            string[] itemNames;
            itemNames = this.sdb.Query(testDataAccess.ForumsDomainName, "['isRoot'='true']");
            Assert.AreEqual(1, itemNames.Length);
            Assert.AreEqual(p.Id, itemNames[0]);

            ISimpleDBAttribute[] attributes;
            attributes = this.sdb.GetAttributes(testDataAccess.ForumsDomainName, p.Id);
            Assert.AreEqual(5, attributes.Length);

            p = new Posting();
            p.Subject = "s2";
            p.Text = "t2";
            p.CreatedBy = "c2";
            this.db.StorePosting(p);

            p = new Posting();
            p.Subject = "s3";
            p.Text = "t3";
            p.CreatedBy = "c3";
            this.db.StorePosting(p);

            itemNames = this.sdb.Query(testDataAccess.ForumsDomainName, "['isRoot'='true']");
            Assert.AreEqual(3, itemNames.Length);
        }

        
        [Test]
        public void testStoreReplyPostings()
        {
            this.db.Initialize();

            Assert.AreEqual(0, this.sdb.Query(testDataAccess.ForumsDomainName, "['isRoot'='true']").Length);

            Posting p;
            p = new Posting();
            p.Subject = "s1";
            p.Text = "t1";
            p.CreatedBy = "c1";
            this.db.StorePosting(p);

            string[] itemNames;
            itemNames = this.sdb.Query(testDataAccess.ForumsDomainName, "['isRoot'='true']");
            Assert.AreEqual(1, itemNames.Length);
            Assert.AreEqual(p.Id, itemNames[0]);

            ISimpleDBAttribute[] attributes;
            attributes = this.sdb.GetAttributes(testDataAccess.ForumsDomainName, p.Id, "replyId");
            Assert.AreEqual(0, attributes.Length);

            Posting pr;
            pr = new Posting(null, p);
            pr.Subject = "s11";
            pr.Text = "t11";
            pr.CreatedBy = "c11";
            this.db.StorePosting(pr);

            Assert.AreEqual(1, this.sdb.Query(testDataAccess.ForumsDomainName, "['isRoot'='true']").Length);
            Assert.AreEqual(2, this.sdb.Query(testDataAccess.ForumsDomainName, "['subject' starts-with '']").Length);

            attributes = this.sdb.GetAttributes(testDataAccess.ForumsDomainName, pr.Id);
            Assert.AreEqual(4, attributes.Length);

            attributes = this.sdb.GetAttributes(testDataAccess.ForumsDomainName, p.Id, "replyId");
            Assert.AreEqual(1, attributes.Length);
            Assert.AreEqual(pr.Id, attributes[0].Value);

            pr = new Posting(null, p);
            pr.Subject = "s12";
            pr.Text = "t12";
            pr.CreatedBy = "c12";
            this.db.StorePosting(pr);
            attributes = this.sdb.GetAttributes(testDataAccess.ForumsDomainName, p.Id, "replyId");
            Assert.AreEqual(2, attributes.Length);
        }


        [Test]
        public void testFind()
        {
            this.db.Initialize();

            Assert.AreEqual(0, this.db.FindPostingsByParent(null).Length);

            Posting p;
            p = new Posting();
            p.Subject = "s1";
            p.Text = "t1";
            p.CreatedBy = "c1";
            this.db.StorePosting(p);

            List<Posting> postings;
            postings = new List<Posting>(this.db.FindPostingsByParent(null));
            Assert.AreEqual(1, postings.Count);
            Assert.AreEqual(p.Id, postings[0].Id);
            Assert.AreEqual("s1", postings[0].Subject);
            Assert.AreEqual("t1", postings[0].Text);
            Assert.AreEqual("c1", postings[0].CreatedBy);
            Assert.AreEqual(p.CreatedAt.ToString("s"), postings[0].CreatedAt.ToString("s"));
            Assert.IsNull(postings[0].Parent);

            p = new Posting();
            p.Subject = "s2";
            p.Text = "t2";
            p.CreatedBy = "c2";
            p.CreatedAt = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
            this.db.StorePosting(p);
            p = new Posting();
            p.Subject = "s3";
            p.Text = "t3";
            p.CreatedBy = "c3";
            p.CreatedAt = DateTime.Now.Subtract(new TimeSpan(2,0,0));
            this.db.StorePosting(p);

            postings = new List<Posting>(this.db.FindPostingsByParent(null));
            postings.Sort(delegate(Posting a, Posting b) { return a.CreatedAt.CompareTo(b.CreatedAt); });
            Assert.AreEqual(3, postings.Count);

            Assert.AreEqual("s3", postings[0].Subject);
            Assert.AreEqual("s2", postings[1].Subject);
            Assert.AreEqual("s1", postings[2].Subject);

            // find replies
            postings = new List<Posting>(this.db.FindPostingsByParent(p));
            Assert.AreEqual(0, postings.Count);

            Posting pr;
            pr = new Posting(null, p);
            pr.Subject = "s11";
            pr.Text = "t11";
            pr.CreatedBy = "c11";
            this.db.StorePosting(pr);

            pr = new Posting(null, p);
            pr.Subject = "s12";
            pr.Text = "t12";
            pr.CreatedBy = "c12";
            this.db.StorePosting(pr);
            postings = new List<Posting>(this.db.FindPostingsByParent(p));
            Assert.AreEqual(2, postings.Count);
        }


        [Test]
        public void testGetReplies()
        {
            this.db.Initialize();

            Posting p, pr;

            p = new Posting(this.db, null);
            p.Subject = "s1";
            p.Text = "t1";
            p.CreatedBy = "c1";
            this.db.StorePosting(p);

            pr = new Posting(this.db, p);
            pr.Subject = "s11";
            pr.Text = "t11";
            pr.CreatedBy = "c11";
            this.db.StorePosting(pr);

            List<Posting> postings;
            postings = p.Replies;
            Assert.AreEqual(1, postings.Count);

            p = new Posting(this.db, null);
            p.Subject = "s2";
            p.Text = "t2";
            p.CreatedBy = "c2";
            this.db.StorePosting(p);

            pr = new Posting(this.db, p);
            pr.Subject = "s21";
            pr.Text = "t21";
            pr.CreatedBy = "c21";
            this.db.StorePosting(pr);
            pr = new Posting(this.db, p);
            pr.Subject = "s22";
            pr.Text = "t22";
            pr.CreatedBy = "c22";
            pr.CreatedAt = new DateTime(2000, 12, 1);
            this.db.StorePosting(pr);

            postings = p.Replies;
            Assert.AreEqual(2, postings.Count);
            Assert.AreEqual("s22", postings[0].Subject);
        }


        [Test]
        [Ignore]
        public void testAppConfig()
        {
            IDataAccess mydb = new Forum.DataAccess.DataAccessAdapter();
            try
            {
                mydb.Initialize();

                Posting p;
                p = new Posting(mydb, null);
                p.Subject = "s1";
                p.Text = "t1";
                p.CreatedBy = "c1";
                mydb.StorePosting(p);

                Posting[] postings;
                postings = mydb.FindPostingsByParent(null);
                Assert.AreEqual(1, postings.Length);
                Assert.AreEqual("s1", postings[0].Subject);
            }
            finally
            {
                mydb.Clear();
                mydb.Dispose();
            }
        }
    }
}
